package com.xuebusi.orm.mybatis.session;

import com.xuebusi.orm.mybatis.config.Configuration;
import com.xuebusi.orm.mybatis.config.MappedStatement;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;
import java.util.Properties;

/**
 * 1.读取配置文件，解析信息， 填充到configuration
 * 2.生产sqlSession
 */
public class SqlSessionFactory {

    private final Configuration conf = new Configuration();

    public SqlSessionFactory() {
        loadDbInfo();
        loadMappersInfo();
    }

    // 记录mapper.xml文件存放的位置
    public static final String MAPPER_CONFIG_LOCATION = "mappers";
    // 记录数据库连接信息文件存放位置
    public static final String DB_CONFIG_FILE = "db.properties";


    // 加载数据库配置信息
    private void loadDbInfo() {
        InputStream dbIn = SqlSessionFactory.class.getClassLoader().getResourceAsStream(DB_CONFIG_FILE);
        Properties p = new Properties();
        try {
            p.load(dbIn);// 将配置信息写入Properties对象
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 将数据库配置信息写入conf对象
        conf.setJdbcDriver(p.get("jdbc.driver").toString());
        conf.setJdbcUrl(p.get("jdbc.url").toString());
        conf.setJdbcUsername(p.get("jdbc.username").toString());
        conf.setJdbcPassword(p.get("jdbc.password").toString());
    }

    // 加载指定文件夹下的所有mapper.xml
    private void loadMappersInfo() {
        URL resources = SqlSessionFactory.class.getClassLoader().getResource(MAPPER_CONFIG_LOCATION);
        File mappers = new File(resources.getFile());// 获取指定文件夹信息
        if (mappers.isDirectory()) {
            File[] listFiles = mappers.listFiles();
            // 遍历文件夹下所有的mapper.xml，解析信息后，注册至conf对象中
            for (File file : listFiles) {
                loadMappersInfo(file);
            }
        }
    }

    // 加载指定的mapper.xml文件
    private void loadMappersInfo(File file) {
        // 创建saxReader对象
        SAXReader reader = new SAXReader();
        // 通过read方法读取一个文件 转换成Document对象
        Document document = null;
        try {
            document = reader.read(file);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        // 获取根节点元素对象 <mapper>
        Element root = document.getRootElement();
        // 获取命名空间
        String namespace = root.attribute("namespace").getData().toString();
        // 获取select子节点列表
        List<Element> selects = root.elements("select");
        // 遍历select节点，将信息记录到MappedStatement对象，并登记到configuration对象中
        for (Element element : selects) {
            MappedStatement mappedStatement = new MappedStatement();
            String id = element.attribute("id").getData().toString();// 读取id属性
            String resultType = element.attribute("resultType").getData().toString();
            String sql = element.getData().toString();// 读取SQL语句信息
            String sourceId = namespace + "." + id;
            // 给mappedStatement属性赋值
            mappedStatement.setSourceId(sourceId);
            mappedStatement.setResultType(resultType);
            mappedStatement.setSql(sql);
            mappedStatement.setNamespace(namespace);
            // 注册到configuration对象中
            conf.getMappedStatements().put(sourceId, mappedStatement);
        }
    }

    public SqlSession openSqlSession() {
        return new DefaultSqlSession(conf);
    }
}
